package org.jadapter.registry;

import org.jadapter.Adapter;
import org.jadapter.AdapterFactory;
import org.jadapter.JAdapter;
import org.jadapter.func.Lambda;

/**
 * Common super class for adapter registries. 
 * It implements all registration methods 
 * except {@code register(AdapterFactory<?,?> adapter)}, 
 * which is left up to the implementing registry algorithm.
 * 
 * 
 * @author Vidar Svansson
 * 
 * @since 0.1
 * 
 * @see AdapterRegistry
 * @see TransitiveAdapterRegistry
 * @see AbstractComponentRegistry
 * @see SimpleComponentRegistry
 */
public abstract class AbstractAdapterRegistry implements AdapterRegistry {
    
    public abstract void register(AdapterFactory<?,?> adapter);

    

    final public <I,C> void register(
            Class<I> provides, 
            Class<?> adapter, 
            Class<C> adaptable) {
        JAdapter<I,C> jadapter = new JAdapter<I,C>();
        jadapter.setProvides(provides);
        jadapter.setFor(adaptable);
        jadapter.setAdapter(adapter);
        register(jadapter);
    } 
    
    
    final public <I,C> void register(
            final Class<I> provides,
            final Lambda<I,C> adapter,
            final Class<C> context ) {
        
        register ( new AdapterFactory<I,C>(){
            public Class<I> provides() { return provides; }
            public Class<C> context()  { return context; }

            public I adapt(C item) {
                return adapter.x(item);
            }
            
        });     
    }
    
   
    @SuppressWarnings("unchecked")
    final public <I,C> void register(
            Class<I> provides, 
            Adapter<I,C> adapter, 
            Class<C> adaptable) {
        JAdapter<I,C> jadapter = new JAdapter<I,C>();
        jadapter.setProvides(provides);
        jadapter.setFor(adaptable);
        jadapter.setAdapter(adapter);
        register(jadapter);
    }  
    

    public void registerAdapters(Iterable<AdapterFactory<?,?>> adapters){
        for(AdapterFactory<?,?> adapter : adapters){
            register(adapter);
        }
    }    
    
    public void register(AdapterFactory<?,?> ... adapters){
        for(AdapterFactory<?,?> adapter : adapters){
            register(adapter);
        }       
    }


}
